Search

📜 [專欄新文章] Solidity Data Collision

✍️ Wi...

  • Share this:

📜 [專欄新文章] Solidity Data Collision

✍️ Wias Liaw

📥 歡迎投稿: https://medium.com/taipei-ethereum-meetup #徵技術分享文 #使用心得 #教學文 #medium

這是一篇關於 Proxy Contract 和 delegatecall 的注意事項。

Delegatecall

當 A 合約對 B 合約執行 delegatecall 時,B 合約的函式會被執行,但是對 storage 的操作都會作用在 A 合約上。舉例如下:

但是假如多加了一個 other 欄位在 _value 之前,執行合約之後反而是 other 欄位被更改了。

Storage Layout

了解上面的合約之前要先了解 Solidity 怎麼儲存 State Variables。Solidity Storage 以 Slot 為單位,每個 Slot 可以儲存 32 bytes 的資訊,一個 Contract 擁有 2**256 個 Slot。上述可以寫成一個映射關係 mapping(uint256 => bytes32) slots。

Solidity 會從 Slot Index 為零開始分配給 State Variable。

除了 mapping 和 dynamically-sized array,其他的 State Variable 會從 index 為零的 slot 開始被分配。

沒有宣告確切大小的 Array 會以 Slot Index 計算出一個雜湊值並將其作為 Slot Index。透過計算 keccak256(slot) 可以得知 _arr[0] 被存在哪裡,如果要取得 _arr[1] 則將計算出來的雜湊加上 Array 的 index 即可。

Mapping 則是以 Slot Index 和 Key 計算出一個雜湊值並將其作為 Slot Index。透過計算 keccak256(key, slot) 可以得到 mapping(key => value) 被存在哪。

Storage Collision

回到 DelegateExample_v2 的合約,對 B 來說, add 最後儲存加法的 Slot Index 為零,所以使用 A 的 Storage 執行 B 的函式結果自然會儲存在 A 的 other 裡,其 Slot Index 為 0。

這個問題也發生在 Proxy Contract,Layout 如下,當有需要更改 _owner 的操作,就會順帶把 _implementation 也更改了。

|Proxy |Implementation ||--------------------------|-------------------------||address _implementation |address _owner | <= collision|... |mapping _balances || |uint256 _supply || |... |

OpenZeppelin 處理的手法也很簡單,就是將 _implementation 換地方擺。以特定字串的雜湊值作為 Slot Index,儲存 Implementation 的地址。

|Proxy |Implementation ||--------------------------|-------------------------||... |address _owner ||... |mapping _balances ||... |uint256 _supply ||... |... ||address _implementation | | <= specified|... | |

openzeppelin-contracts/ERC1967Upgrade.sol at 83644fdb6a9f75a652d2fe2d96cb26073a14f6f8 · OpenZeppelin/openzeppelin-contracts

hardhat-storage-layout

如何知道合約的 Storage Layout 呢?這邊推薦一個 Hardhat Plugin,按照文件就能得到合約的 Storage Layout。

Ethereum development environment for professionals by Nomic Labs

Reference

Understanding Ethereum Smart Contract Storage

Collisions of Solidity Storage Layouts

Proxy Upgrade Pattern - OpenZeppelin Docs

Solidity Data Collision was originally published in Taipei Ethereum Meetup on Medium, where people are continuing the conversation by highlighting and responding to this story.

👏 歡迎轉載分享鼓掌


Tags:

About author
not provided
We have regular meeting twice per month on discussing blockchain technology, smart contracts and DApps development! We would love to have you join us!
View all posts